home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fsrmt / fsrmtAttributes.c < prev    next >
C/C++ Source or Header  |  1991-02-01  |  36KB  |  1,073 lines

  1. /*
  2.  * fsAttributes.c --
  3.  *
  4.  *    This has procedures for operations done on remote file attributes.
  5.  *    The general strategy when getting attributes is to make one call to
  6.  *    the name server to get an initial version of the attributes, and
  7.  *    then make another call to the I/O server to update things like
  8.  *    the access time and modify time.  There are two ways to get to
  9.  *    the name server, either via a pathname or an open file.  The
  10.  *    I/O server is always contacted using a fileID.
  11.  *    The 3 corrsponding RPCs are:
  12.  *    RPC_FS_GET_ATTR_PATH    To get attributes from name server given path.
  13.  *    RPC_FS_GET_ATTR        To get attributes from name server given fileID
  14.  *    RPC_FS_GET_IO_ATTR    To get (a few) attributes from the I/O server.
  15.  *    Setting attributes is done the same way, and there are three more
  16.  *    corresponding RPCs.
  17.  *
  18.  * Copyright 1987 Regents of the University of California
  19.  * All rights reserved.
  20.  * Permission to use, copy, modify, and distribute this
  21.  * software and its documentation for any purpose and without
  22.  * fee is hereby granted, provided that the above copyright
  23.  * notice appear in all copies.  The University of California
  24.  * makes no representations about the suitability of this
  25.  * software for any purpose.  It is provided "as is" without
  26.  * express or implied warranty.
  27.  */
  28.  
  29. #ifndef lint
  30. static char rcsid[] = "$Header: /sprite/src/kernel/fsrmt/RCS/fsrmtAttributes.c,v 9.8 91/02/01 16:33:17 shirriff Exp $ SPRITE (Berkeley)";
  31. #endif not lint
  32.  
  33.  
  34. #include <sprite.h>
  35. #include <fs.h>
  36. #include <fsutil.h>
  37. #include <fslcl.h>
  38. #include <fsNameOps.h>
  39. #include <fsconsist.h>
  40. #include <fscache.h>
  41. #include <fsdm.h>
  42. #include <fsStat.h>
  43. #include <recov.h>
  44. #include <rpc.h>
  45. #ifdef SOSP91
  46. #include <sospRecord.h>
  47. #endif
  48.  
  49. #include <string.h>
  50. #include <stdio.h>
  51.  
  52. static Fs_HandleHeader *VerifyIOHandle _ARGS_((Fs_FileID *fileIDPtr));
  53.  
  54.  
  55. /*
  56.  * Return parameters from RPC_FS_GET_ATTR_PATH.  The file ID is used to
  57.  * get to the I/O server.
  58.  */
  59. typedef struct FsRemoteGetAttrResults {
  60.     Fs_Attributes    attributes;
  61.     Fs_FileID        fileID;
  62. } FsRemoteGetAttrResults;
  63.  
  64.  
  65. /*
  66.  *----------------------------------------------------------------------
  67.  *
  68.  * FsrmtGetAttrPath --
  69.  *
  70.  *    Get the attributes of a remote Sprite file given its name.  This
  71.  *    is called from Fs_GetAttributes for files named by remote servers.
  72.  *    Note:  the attributes from the disk descriptor on the name server
  73.  *    are returned.  The attributes need to be updated by the I/O server
  74.  *    if there is one.
  75.  *
  76.  * Results:
  77.  *    A return code from the RPC or the remote server.
  78.  *
  79.  * Side effects:
  80.  *    FS_RPC_GET_ATTR.
  81.  *
  82.  *----------------------------------------------------------------------
  83.  */
  84. ReturnStatus
  85. FsrmtGetAttrPath(prefixHandle, relativeName, argsPtr, resultsPtr,
  86.                  newNameInfoPtrPtr)
  87.     Fs_HandleHeader *prefixHandle;    /* Handle from the prefix table */
  88.     char           *relativeName;    /* The name of the file. */
  89.     Address        argsPtr;        /* Bundled arguments for us */
  90.     Address        resultsPtr;        /* Where to store attributes */
  91.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  92.                      * its domain during the lookup. */
  93. {
  94.     ReturnStatus         status;
  95.     Fs_OpenArgs            *openArgsPtr;
  96.     Fs_GetAttrResults        *getAttrResultsPtr;
  97.     Fs_GetAttrResultsParam    getAttrResultsParam;
  98.     Rpc_Storage            storage;
  99.     char            replyName[FS_MAX_PATH_NAME_LENGTH];     /* This
  100.                              * may get filled with a
  101.                              * redirected pathname. */
  102.  
  103.     openArgsPtr = (Fs_OpenArgs *) argsPtr;
  104.     getAttrResultsPtr = (Fs_GetAttrResults *)resultsPtr;
  105.  
  106.     storage.requestParamPtr = (Address) openArgsPtr;
  107.     storage.requestParamSize = sizeof(Fs_OpenArgs);
  108.     storage.requestDataPtr = (Address) relativeName;
  109.     storage.requestDataSize = strlen(relativeName) + 1;
  110.     storage.replyParamPtr = (Address) &(getAttrResultsParam);
  111.     storage.replyParamSize = sizeof(Fs_GetAttrResultsParam);
  112.     storage.replyDataPtr = (Address) replyName;
  113.     storage.replyDataSize = FS_MAX_PATH_NAME_LENGTH;
  114.  
  115.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_GET_ATTR_PATH,
  116.             &storage);
  117.      if (status == SUCCESS) {
  118.     /*
  119.      * The return param area has a fileID that we need.  The
  120.      * return parameter area has also been filled in with
  121.      * the attributes.
  122.      */
  123.     *(getAttrResultsPtr->fileIDPtr) =
  124.          getAttrResultsParam.attrResults.fileID;
  125.     *(getAttrResultsPtr->attrPtr) =
  126.         getAttrResultsParam.attrResults.attrs;
  127.     } else if (status == FS_LOOKUP_REDIRECT) {
  128.     /*
  129.      * Copy the info from our stack to a buffer for our caller
  130.      */
  131.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  132.     (*newNameInfoPtrPtr)->prefixLength = getAttrResultsParam.prefixLength;
  133.     (void)strcpy((*newNameInfoPtrPtr)->fileName, replyName);
  134.     return(FS_LOOKUP_REDIRECT);
  135.     }
  136.  
  137.     return(status);
  138. }
  139.  
  140. /*
  141.  *----------------------------------------------------------------------
  142.  *
  143.  * Fsrmt_RpcGetAttrPath --
  144.  *
  145.  *    Service stub for the RPC_FS_GET_ATTR_PATH call.  This is used to
  146.  *    get the attributes from the disk descriptor of a file.  NOTE:  the
  147.  *    attributes are not complete until the I/O server for the (non-regular)
  148.  *    file is contacted.  This routine does, however, suck in attributes
  149.  *    of regular files that are cached.
  150.  *
  151.  * Results:
  152.  *    If this procedure returns SUCCESS then a reply has been sent to
  153.  *    the client.  If the arguments are bad then an error is 
  154.  *    returned and the main level sends back an error reply.
  155.  *
  156.  * Side effects:
  157.  *    Allocates a buffer to return the results in.
  158.  *    
  159.  *
  160.  *----------------------------------------------------------------------
  161.  */
  162. /*ARGSUSED*/
  163. ReturnStatus
  164. Fsrmt_RpcGetAttrPath(srvToken, clientID, command, storagePtr)
  165.     ClientData          srvToken;    /* Handle on server process passed to
  166.                       * Rpc_Reply */
  167.     int          clientID;    /* Sprite ID of client host */
  168.     int          command;    /* IGNORED */
  169.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  170.                      * request buffers and also indicate 
  171.                      * the exact amount of data in the 
  172.                      * request buffers.  The reply fields 
  173.                      * are initialized to NIL for the
  174.                       * pointers and 0 for the lengths.  
  175.                      * This can be passed to Rpc_Reply */
  176. {
  177.     register Fs_OpenArgs        *openArgsPtr;    /* Tmp pointer into openParams*/
  178.     Fs_GetAttrResults         getAttrResults;    /* Results from local  routine */
  179.     Fs_GetAttrResultsParam    *getAttrResultsParamPtr;    /* rpc param
  180.                                  * bundle */
  181.     Fs_HandleHeader        *prefixHandle;    /* Handle for domain */
  182.     ReturnStatus        status;        /* General return code */
  183.     Fs_RedirectInfo        *newNameInfoPtr;/* For prefix re-directs,
  184.                          * unallocated since proc call
  185.                          * allocates space for it. */
  186.     int                domainType;
  187.  
  188.     openArgsPtr = (Fs_OpenArgs *) storagePtr->requestParamPtr;
  189.  
  190.     if (openArgsPtr->prefixID.serverID != rpc_SpriteID) {
  191.     /*
  192.      * Filesystem mis-match.
  193.      */
  194.     return(GEN_INVALID_ARG);
  195.     }
  196.     prefixHandle = (*fsio_StreamOpTable[openArgsPtr->prefixID.type].clientVerify)
  197.         (&openArgsPtr->prefixID, clientID, &domainType);
  198.     if (prefixHandle == (Fs_HandleHeader *)NIL) {
  199.     return(FS_STALE_HANDLE);
  200.     }
  201.     Fsutil_HandleRelease(prefixHandle, TRUE);
  202.  
  203.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  204.     getAttrResultsParamPtr = mnew(Fs_GetAttrResultsParam);
  205.  
  206.     getAttrResults.attrPtr = &(getAttrResultsParamPtr->attrResults.attrs);
  207.     getAttrResults.fileIDPtr = &(getAttrResultsParamPtr->attrResults.fileID);
  208.  
  209.     fs_Stats.srvName.getAttrs++;
  210.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_GET_ATTR])(prefixHandle,
  211.         (char *) storagePtr->requestDataPtr, (Address)openArgsPtr,
  212.         (Address)(&getAttrResults), &newNameInfoPtr);
  213.  
  214.     if (status == SUCCESS) {
  215.     storagePtr->replyParamPtr = (Address) getAttrResultsParamPtr;
  216.     storagePtr->replyParamSize = sizeof(Fs_GetAttrResultsParam);
  217.     storagePtr->replyDataPtr = (Address) NIL;
  218.     storagePtr->replyDataSize = 0;
  219.     } else if (status == FS_LOOKUP_REDIRECT) {
  220.     /*
  221.      * The file is not found on this server, but somewhere else.
  222.      */
  223.     getAttrResultsParamPtr->prefixLength = newNameInfoPtr->prefixLength;
  224.     storagePtr->replyParamPtr = (Address) getAttrResultsParamPtr;
  225.     storagePtr->replyParamSize = sizeof(Fs_GetAttrResultsParam);
  226.     storagePtr->replyDataSize = strlen(newNameInfoPtr->fileName) + 1;
  227.     storagePtr->replyDataPtr =
  228.         (Address) malloc(storagePtr->replyDataSize);
  229.     (void)strcpy((char *) storagePtr->replyDataPtr, newNameInfoPtr->fileName);
  230.     free((Address)newNameInfoPtr);
  231.     }
  232.     if (status == SUCCESS || status == FS_LOOKUP_REDIRECT) {
  233.     Rpc_ReplyMem    *replyMemPtr;
  234.  
  235.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  236.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  237.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  238.         Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  239.             (ClientData)replyMemPtr);
  240.         return(SUCCESS);
  241.     } else {
  242.     free((Address) getAttrResultsParamPtr);
  243.         return(status);
  244.     }
  245. }
  246.  
  247.  
  248. /*
  249.  *----------------------------------------------------------------------
  250.  *
  251.  * FsrmtSetAttrPath --
  252.  *
  253.  *    Set the attributes of a remote Sprite file given its path name.
  254.  *    This is called from Fs_SetAttributes.  This used the
  255.  *    RPC_FS_SET_ATTR_PATH rpc to invoke FslclSetAttrPath on the
  256.  *    name server.
  257.  *
  258.  * Results:
  259.  *    None.
  260.  *
  261.  * Side effects:
  262.  *    None.
  263.  *
  264.  *----------------------------------------------------------------------
  265.  */
  266.  
  267. ReturnStatus
  268. FsrmtSetAttrPath(prefixHandle, relativeName, argsPtr, resultsPtr,
  269.                  newNameInfoPtrPtr)
  270.     Fs_HandleHeader *prefixHandle;   /* Token from the prefix table */
  271.     char           *relativeName;   /* The name of the file. */
  272.     Address        argsPtr;        /* Bundled arguments for us */
  273.     Address        resultsPtr;        /* FileID */
  274.     Fs_RedirectInfo **newNameInfoPtrPtr; /* We return this if the server leaves 
  275.                      * its domain during the lookup. */
  276. {
  277.     ReturnStatus         status;
  278.     Rpc_Storage            storage;
  279.     char            replyName[FS_MAX_PATH_NAME_LENGTH];
  280.     Fs_GetAttrResultsParam    getAttrResultsParam;
  281.     Fs_FileID            *fileIDPtr;
  282.  
  283.     storage.requestParamPtr = (Address) argsPtr;
  284.     storage.requestParamSize = sizeof(Fs_SetAttrArgs);
  285.     storage.requestDataPtr = (Address) relativeName;
  286.     storage.requestDataSize = strlen(relativeName) + 1;
  287.     storage.replyParamPtr = (Address) &(getAttrResultsParam);
  288.     storage.replyParamSize = sizeof(Fs_GetAttrResultsParam);
  289.     storage.replyDataPtr = (Address) replyName;
  290.     storage.replyDataSize = FS_MAX_PATH_NAME_LENGTH;
  291.  
  292.     fileIDPtr = (Fs_FileID *) resultsPtr;
  293.  
  294.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_SET_ATTR_PATH,
  295.             &storage);
  296.     if (status == SUCCESS) {
  297.     /*
  298.      * Copy result fileID to resultsPtr (== fileIDPtr).
  299.      */
  300.     (* fileIDPtr) = getAttrResultsParam.attrResults.fileID;
  301.     } else if (status == FS_LOOKUP_REDIRECT) {
  302.     /*
  303.      * Copy the info from our stack to a buffer for our caller.
  304.      */
  305.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  306.     (*newNameInfoPtrPtr)->prefixLength = getAttrResultsParam.prefixLength;
  307.     (void)strcpy((*newNameInfoPtrPtr)->fileName, replyName);
  308.     }
  309.  
  310.     return(status);
  311. }
  312.  
  313. /*
  314.  *----------------------------------------------------------------------
  315.  *
  316.  * Fsrmt_RpcSetAttrPath --
  317.  *
  318.  *    Service stub for the RPC_FS_SET_ATTR_PATH call.  This branches
  319.  *    to FslclSetAttrPath which sets the attributes on the file descriptor.
  320.  *
  321.  * Results:
  322.  *    If this procedure returns SUCCESS then a reply has been sent to
  323.  *    the client.  If the arguments are bad then an error is 
  324.  *    returned and the main level sends back an error reply.
  325.  *
  326.  * Side effects:
  327.  *    Allocates a buffer to return the results in.
  328.  *    
  329.  *
  330.  *----------------------------------------------------------------------
  331.  */
  332. /*ARGSUSED*/
  333. ReturnStatus
  334. Fsrmt_RpcSetAttrPath(srvToken, clientID, command, storagePtr)
  335.     ClientData          srvToken;    /* Handle on server process passed to
  336.                       * Rpc_Reply */
  337.     int          clientID;    /* Sprite ID of client host */
  338.     int          command;    /* IGNORED */
  339.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  340.                      * request buffers and also indicate 
  341.                      * the exact amount of data in the 
  342.                      * request buffers.  The reply fields 
  343.                      * are initialized to NIL for the
  344.                       * pointers and 0 for the lengths.  
  345.                      * This can be passed to Rpc_Reply */
  346. {
  347.     Fs_FileID            *ioFileIDPtr;    /* Results from local routine */
  348.     Fs_HandleHeader        *prefixHandle;    /* Handle for domain */
  349.     ReturnStatus        status;        /* General return code */
  350.     Fs_SetAttrArgs        *setAttrArgsPtr;
  351.     Fs_RedirectInfo        *newNameInfoPtr;/* For prefix re-directs */
  352.     Fs_GetAttrResultsParam    *getAttrResultsParamPtr;    /* rpc param
  353.                                  * bundle */
  354.     int                domainType;
  355.  
  356.     setAttrArgsPtr = (Fs_SetAttrArgs *) storagePtr->requestParamPtr;
  357.  
  358.     prefixHandle =
  359.     (*fsio_StreamOpTable[setAttrArgsPtr->openArgs.prefixID.type].clientVerify)
  360.         (&setAttrArgsPtr->openArgs.prefixID, clientID, &domainType);
  361.     if (prefixHandle == (Fs_HandleHeader *)NIL) {
  362.     return(FS_STALE_HANDLE);
  363.     }
  364.     Fsutil_HandleRelease(prefixHandle, TRUE);
  365.  
  366.  
  367.     fs_Stats.srvName.setAttrs++;
  368.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  369.     getAttrResultsParamPtr = mnew(Fs_GetAttrResultsParam);
  370.     ioFileIDPtr = &(getAttrResultsParamPtr->attrResults.fileID);
  371.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_SET_ATTR])(prefixHandle,
  372.         (char *) storagePtr->requestDataPtr,
  373.         (Address) storagePtr->requestParamPtr,
  374.         (Address) ioFileIDPtr, &newNameInfoPtr);
  375.  
  376.     if (status == SUCCESS) {
  377.     storagePtr->replyParamPtr = (Address) getAttrResultsParamPtr;
  378.     storagePtr->replyParamSize = sizeof(Fs_GetAttrResultsParam);
  379.     storagePtr->replyDataPtr = (Address) NIL;
  380.     storagePtr->replyDataSize = 0;
  381.     } else if (status == FS_LOOKUP_REDIRECT) {
  382.     /*
  383.      * The file is not found on this server.
  384.      */
  385.     getAttrResultsParamPtr->prefixLength = newNameInfoPtr->prefixLength;
  386.     storagePtr->replyParamPtr = (Address) getAttrResultsParamPtr;
  387.     storagePtr->replyParamSize = sizeof(Fs_GetAttrResultsParam);
  388.     storagePtr->replyDataSize = strlen(newNameInfoPtr->fileName) + 1;
  389.     storagePtr->replyDataPtr =
  390.         (Address) malloc(storagePtr->replyDataSize);
  391.     (void)strcpy((char *) storagePtr->replyDataPtr, newNameInfoPtr->fileName);
  392.     free((Address)newNameInfoPtr);
  393.     }
  394.     if (status == SUCCESS || status == FS_LOOKUP_REDIRECT) {
  395.     Rpc_ReplyMem    *replyMemPtr;
  396.  
  397.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  398.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  399.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  400.         Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  401.         (ClientData)replyMemPtr);
  402.         return(SUCCESS);
  403.     } else {
  404.     free((Address)getAttrResultsParamPtr);
  405.         return(status);
  406.     }
  407. }
  408.  
  409. /*
  410.  *----------------------------------------------------------------------
  411.  *
  412.  * FsrmtGetAttr --
  413.  *
  414.  *    Get the attributes of a remote file given its fileID.  This is called
  415.  *    from Fs_GetAttrStream.  This does an RPC to the name server which
  416.  *    then calls FslclGetAttr.
  417.  *
  418.  * Results:
  419.  *    An error code.
  420.  *
  421.  * Side effects:
  422.  *    Fills in the attributes structure with info from the file server.
  423.  *
  424.  *----------------------------------------------------------------------
  425.  */
  426. /*ARGSUSED*/
  427. ReturnStatus
  428. #ifdef SOSP91
  429. FsrmtGetAttr(fileIDPtr, clientID, attrPtr, hostID, userID)
  430.     register Fs_FileID        *fileIDPtr;    /* Identfies file */
  431.     int                clientID;    /* IGNORED, implicitly passed
  432.                          * by the RPC system. */
  433.     register Fs_Attributes    *attrPtr;    /* Return - the attributes */
  434.     int hostID, userID;
  435. #else
  436. FsrmtGetAttr(fileIDPtr, clientID, attrPtr)
  437.     register Fs_FileID        *fileIDPtr;    /* Identfies file */
  438.     int                clientID;    /* IGNORED, implicitly passed
  439.                          * by the RPC system. */
  440.     register Fs_Attributes    *attrPtr;    /* Return - the attributes */
  441. #endif
  442. {
  443.     register ReturnStatus    status;
  444.     Rpc_Storage storage;
  445.  
  446. #ifdef SOSP91
  447.     int buf[6];
  448.     bcopy((char *)fileIDPtr, (char *)buf, 16);
  449.     buf[5] = hostID;
  450.     buf[6] = userID;
  451.     storage.requestParamPtr = (Address) buf;
  452.     storage.requestParamSize = sizeof(Fs_FileID)+2*sizeof(int);
  453.     storage.requestDataPtr = (Address) NIL;
  454.     storage.requestDataSize = 0;
  455. #else
  456.     storage.requestParamPtr = (Address) fileIDPtr;
  457.     storage.requestParamSize = sizeof(Fs_FileID);
  458.     storage.requestDataPtr = (Address) NIL;
  459.     storage.requestDataSize = 0;
  460. #endif
  461.  
  462.     storage.replyParamPtr = (Address) attrPtr;
  463.     storage.replyParamSize = sizeof(Fs_Attributes);
  464.     storage.replyDataPtr = (Address) NIL;
  465.     storage.replyDataSize = 0;
  466.  
  467.     status = Rpc_Call(fileIDPtr->serverID, RPC_FS_GET_ATTR, &storage);
  468.     if (status == RPC_TIMEOUT || status == FS_STALE_HANDLE ||
  469.     status == RPC_SERVICE_DISABLED) {
  470.     /*
  471.      * If there was a problem at the server then try to recover
  472.      * the handle.  We may not have a handle in the case of devices.
  473.      * In that case the fileID we have here comes from the stream's
  474.      * nameInfo, which doesn't get installed into the handle table.
  475.      */
  476.     register Fs_HandleHeader *hdrPtr = Fsutil_HandleFetch(fileIDPtr);
  477.     if (hdrPtr != (Fs_HandleHeader *)NIL) {
  478.         Fsutil_WantRecovery(hdrPtr);
  479.         Fsutil_HandleRelease(hdrPtr, TRUE);
  480.     }
  481.     }
  482.     return(status);
  483. }
  484.  
  485. /*
  486.  *----------------------------------------------------------------------
  487.  *
  488.  * Fsrmt_RpcGetAttr --
  489.  *
  490.  *    Service stub for the RPC_FS_GET_ATTR call.  This calls FslclGetAttr
  491.  *    (or FspdevPseudoGetAttr) to get the attributes of a file.  This
  492.  *    is a name server operation used when the file is already open.
  493.  *    Note: Attributes are not complete until the I/O server has also
  494.  *    been contacted.  See Fsrmt_RpcGetIOAttr.
  495.  *
  496.  * Results:
  497.  *    If this procedure returns SUCCESS then a reply has been sent to
  498.  *    the client.  If the arguments are bad then an error is 
  499.  *    returned and the main level sends back an error reply.
  500.  *
  501.  * Side effects:
  502.  *    Allocates a buffer to return the results in.
  503.  *
  504.  *----------------------------------------------------------------------
  505.  */
  506. /*ARGSUSED*/
  507. ReturnStatus
  508. Fsrmt_RpcGetAttr(srvToken, clientID, command, storagePtr)
  509.     ClientData          srvToken;    /* Handle on server process passed to
  510.                       * Rpc_Reply */
  511.     int          clientID;    /* Sprite ID of client host */
  512.     int          command;    /* IGNORED */
  513.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  514.                      * request buffers and also indicate 
  515.                      * the exact amount of data in the 
  516.                      * request buffers.  The reply fields 
  517.                      * are initialized to NIL for the
  518.                      * pointers and 0 for the lengths.  
  519.                      * This can be passed to Rpc_Reply */
  520. {
  521.     register ReturnStatus    status;
  522.     Fs_HandleHeader        *tHdrPtr;
  523.     register Fs_HandleHeader    *hdrPtr;
  524.     register Fs_FileID        *fileIDPtr;
  525.     register Fs_Attributes    *attrPtr;
  526.     Rpc_ReplyMem        *replyMemPtr;
  527.     int                domainType = FS_LOCAL_DOMAIN;
  528.  
  529.     fileIDPtr = (Fs_FileID *) storagePtr->requestParamPtr;
  530.     hdrPtr = VerifyIOHandle(fileIDPtr);
  531.     if (fileIDPtr->type == FSIO_LCL_PFS_STREAM) {
  532.     if (hdrPtr == (Fs_HandleHeader *)NIL) {
  533.         return(FS_STALE_HANDLE);
  534.     }
  535.     domainType = FS_PSEUDO_DOMAIN;
  536.     } else if (hdrPtr == (Fs_HandleHeader *)NIL) {
  537.     status = Fsio_LocalFileHandleInit(fileIDPtr, (char *)NIL,
  538.             (Fsdm_FileDescriptor *) NIL, FALSE, 
  539.             (Fsio_FileIOHandle **)&tHdrPtr);
  540.     if (status != SUCCESS) {
  541.         return(status);
  542.     }
  543.     hdrPtr = tHdrPtr;
  544.     }
  545.     Fsutil_HandleUnlock(hdrPtr);
  546.  
  547.     fs_Stats.srvName.getAttrs++;
  548.     attrPtr = mnew(Fs_Attributes);
  549. #ifdef SOSP91
  550.     status = (*fs_AttrOpTable[domainType].getAttr)(fileIDPtr, clientID,
  551.         attrPtr, ((int *)storagePtr->requestParamPtr)[5],
  552.         ((int *)storagePtr->requestParamPtr)[6]);
  553. #else
  554.     status = (*fs_AttrOpTable[domainType].getAttr)(fileIDPtr, clientID, attrPtr);
  555. #endif
  556. #ifdef lint
  557.     status = FslclGetAttr(fileIDPtr, clientID, attrPtr);
  558.     status = FspdevPseudoGetAttr(fileIDPtr, clientID, attrPtr);
  559. #endif lint
  560.     Fsutil_HandleRelease(hdrPtr, FALSE);
  561.  
  562.     storagePtr->replyParamPtr = (Address) attrPtr;
  563.     storagePtr->replyParamSize = sizeof(Fs_Attributes);
  564.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  565.     replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  566.     replyMemPtr->dataPtr = (Address) NIL;
  567.  
  568.     Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  569.         (ClientData)replyMemPtr);
  570.     return(SUCCESS);
  571. }
  572.  
  573. /*
  574.  * Parameters for RPC_FS_SET_ATTR.  This is a sub-set of Fs_SetAttrArgs
  575.  * (which has extra stuff required to handle path name lookup).
  576.  */
  577.  
  578. typedef struct FsRemoteSetAttrParams {
  579.     Fs_FileID        fileID;
  580.     Fs_UserIDs        ids;
  581.     Fs_Attributes    attrs;
  582.     int            flags;
  583. #ifdef SOSP91
  584.     int            hostID;
  585.     int            userID;
  586. #endif
  587. } FsRemoteSetAttrParams;
  588.  
  589. /*
  590.  *----------------------------------------------------------------------
  591.  *
  592.  * FsrmtSetAttr
  593.  *
  594.  *    Set selected attributes of a remote file given its fileID.  This
  595.  *    is called from Fs_SetAttrStream.  This does the RPC_FS_SET_ATTR
  596.  *    remote call which invokes FslclSetAttr on the name server.
  597.  *
  598.  * Results:
  599.  *    None.
  600.  *
  601.  * Side effects:
  602.  *    None.
  603.  *
  604.  *----------------------------------------------------------------------
  605.  */
  606.  
  607. ReturnStatus
  608. #ifdef SOSP91
  609. FsrmtSetAttr(fileIDPtr, attrPtr, idPtr, flags, clientID, hostID, userID)
  610.     Fs_FileID        *fileIDPtr;
  611.     Fs_Attributes    *attrPtr;
  612.     Fs_UserIDs         *idPtr;
  613.     int            flags;
  614.     int            clientID;
  615.     int            hostID;
  616.     int            userID;
  617. #else
  618. FsrmtSetAttr(fileIDPtr, attrPtr, idPtr, flags)
  619.     Fs_FileID        *fileIDPtr;
  620.     Fs_Attributes    *attrPtr;
  621.     Fs_UserIDs         *idPtr;
  622.     int            flags;
  623. #endif
  624. {
  625.     ReturnStatus status;
  626.     Rpc_Storage storage;
  627.     FsRemoteSetAttrParams params;
  628.  
  629.     params.fileID = *fileIDPtr;
  630.     params.ids = *idPtr;
  631.     params.attrs = *attrPtr;
  632.     params.flags = flags;
  633. #ifdef SOSP91
  634.     params.hostID = hostID;
  635.     params.userID = userID;
  636. #endif
  637.     storage.requestParamPtr = (Address)¶ms;
  638.     storage.requestParamSize = sizeof(FsRemoteSetAttrParams);
  639.     storage.requestDataPtr = (Address)NIL;;
  640.     storage.requestDataSize = 0;
  641.     storage.replyParamPtr = (Address)NIL;
  642.     storage.replyParamSize = 0;
  643.     storage.replyDataPtr = (Address)NIL;
  644.     storage.replyDataSize = 0;
  645.  
  646.     status = Rpc_Call(fileIDPtr->serverID, RPC_FS_SET_ATTR, &storage);
  647.     if (status == RPC_TIMEOUT || status == FS_STALE_HANDLE ||
  648.     status == RPC_SERVICE_DISABLED) {
  649.     register Fs_HandleHeader *hdrPtr = Fsutil_HandleFetch(fileIDPtr);
  650.     if (hdrPtr != (Fs_HandleHeader *)NIL) {
  651.         Fsutil_WantRecovery(hdrPtr);
  652.         Fsutil_HandleRelease(hdrPtr, TRUE);
  653.     }
  654.     }
  655.  
  656.     return(status);
  657. }
  658.  
  659. /*
  660.  *----------------------------------------------------------------------
  661.  *
  662.  * Fsrmt_RpcSetAttr --
  663.  *
  664.  *    Service stub for RPC_FS_SET_ATTR.  This calls FslclSetAttr.
  665.  *
  666.  * Results:
  667.  *    If this procedure returns SUCCESS then a reply has been sent to
  668.  *    the client.  If the arguments are bad then FS_STALE_HANDLE is 
  669.  *    returned and the main level sends back an error reply.
  670.  *
  671.  * Side effects:
  672.  *    Uses FslclSetAttr to set attributes in the file descriptor.
  673.  *
  674.  *----------------------------------------------------------------------
  675.  */
  676. /*ARGSUSED*/
  677. ReturnStatus
  678. Fsrmt_RpcSetAttr(srvToken, clientID, command, storagePtr)
  679.     ClientData          srvToken;    /* Handle on server process passed to
  680.                       * Rpc_Reply */
  681.     int          clientID;    /* Sprite ID of client host */
  682.     int          command;    /* IGNORED */
  683.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  684.                      * request buffers and also indicate 
  685.                      * the exact amount of data in the 
  686.                      * request buffers.  The reply fields 
  687.                      * are initialized to NIL for the
  688.                       * pointers and 0 for the lengths.  
  689.                      * This can be passed to Rpc_Reply */
  690. {
  691.     Fs_HandleHeader        *hdrPtr;
  692.     register Fs_FileID        *fileIDPtr;
  693.     register Fs_Attributes    *attrPtr;
  694.     register ReturnStatus    status;
  695.     FsRemoteSetAttrParams    *paramPtr;
  696.     int                domainType = FS_LOCAL_DOMAIN;
  697.  
  698.     paramPtr = (FsRemoteSetAttrParams *) storagePtr->requestParamPtr;
  699.     attrPtr = ¶mPtr->attrs;
  700.     fileIDPtr = ¶mPtr->fileID;
  701.  
  702.     hdrPtr = VerifyIOHandle(fileIDPtr);
  703.     if (fileIDPtr->type == FSIO_LCL_PFS_STREAM) {
  704.     if (hdrPtr == (Fs_HandleHeader *)NIL) {
  705.         return(FS_STALE_HANDLE);
  706.     }
  707.     domainType = FS_PSEUDO_DOMAIN;
  708.     } else if (hdrPtr == (Fs_HandleHeader *)NIL) {
  709.     status = Fsio_LocalFileHandleInit(fileIDPtr, (char *)NIL,
  710.                 (Fsdm_FileDescriptor *) NIL, FALSE, 
  711.             (Fsio_FileIOHandle **)&hdrPtr);
  712.     if (status != SUCCESS) {
  713.         return(status);
  714.     }
  715.     }
  716.     fs_Stats.srvName.setAttrs++;
  717.     Fsutil_HandleUnlock(hdrPtr);
  718. #ifdef SOSP91
  719.     status = (*fs_AttrOpTable[domainType].setAttr)(fileIDPtr, attrPtr,
  720.         ¶mPtr->ids,paramPtr->flags, clientID,
  721.         paramPtr->hostID, paramPtr->userID);
  722. #else
  723.     status = (*fs_AttrOpTable[domainType].setAttr)(fileIDPtr, attrPtr,
  724.                         ¶mPtr->ids,paramPtr->flags);
  725. #endif
  726. #ifdef lint
  727.     status = FslclSetAttr(fileIDPtr, attrPtr, ¶mPtr->ids,paramPtr->flags);
  728.     status = FspdevPseudoSetAttr(fileIDPtr,attrPtr, ¶mPtr->ids,paramPtr->flags);
  729. #endif lint
  730.     Fsutil_HandleRelease(hdrPtr, FALSE);
  731.  
  732.     Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL,
  733.         (ClientData)NIL);
  734.     return(SUCCESS);
  735. }
  736.  
  737.  
  738. /*
  739.  *----------------------------------------------------------------------
  740.  *
  741.  * Fsrmt_GetIOAttr --
  742.  *
  743.  *    Get the attributes cached at a remote I/O server.  This makes the
  744.  *    RPC_FS_GET_IO_ATTR RPC to the I/O server which then calls
  745.  *    stream-type getIOAttrs routine.
  746.  *
  747.  * Results:
  748.  *    An error code.
  749.  *
  750.  * Side effects:
  751.  *    Update attributes structure with info from the I/O server.
  752.  *
  753.  *----------------------------------------------------------------------
  754.  */
  755. /*ARGSUSED*/
  756. ReturnStatus
  757. Fsrmt_GetIOAttr(fileIDPtr, clientID, attrPtr)
  758.     register Fs_FileID        *fileIDPtr;    /* Remote device/pipe fileID */
  759.     int                clientID;    /* IGNORED, implicitly passed
  760.                          * by the RPC system. */
  761.     register Fs_Attributes    *attrPtr;    /* In/Out - the attributes are
  762.                          * updated by the I/O server */
  763. {
  764.     register ReturnStatus status;
  765.     Rpc_Storage storage;
  766.     Fs_GetAttrResultsParam    getAttrResultsParam;
  767.  
  768.     /*
  769.      * We don't want to do full RPC's to hosts we're pretty sure are down.
  770.      */
  771.     if (Recov_IsHostDown(fileIDPtr->serverID) == FAILURE) {
  772.     printf(
  773.         "Fsrmt_GetIOAttr: skipping device <%d,%d> at server %d: host is down.\n",
  774.         fileIDPtr->major, fileIDPtr->minor, fileIDPtr->serverID);
  775.     return(SUCCESS);
  776.     }
  777.  
  778.     getAttrResultsParam.attrResults.fileID = *fileIDPtr;
  779.     getAttrResultsParam.attrResults.attrs = *attrPtr;
  780.     /*
  781.      * We have to fix up the fileID of control handles in the case that
  782.      * the pseudo-device server is remote from us.  The problem is that
  783.      * we have to RPC to the pseduo-device server, but the fileID of the
  784.      * control stream (where the access/modify times are) has the
  785.      * file serverID.  Fortuneatly this is in the regular attributes so
  786.      * we can patch it up.  We add two lines of code here instead of
  787.      * nearly duplicating this procedure into a FsRmtControlGetIOAttr
  788.      * routine that has the patch.
  789.      */
  790.     if (fileIDPtr->type == FSIO_RMT_CONTROL_STREAM) {
  791.     getAttrResultsParam.attrResults.fileID.serverID = attrPtr->serverID;
  792.     }
  793.  
  794.     storage.requestParamPtr = (Address) &getAttrResultsParam;
  795.     storage.requestParamSize = sizeof(Fs_GetAttrResultsParam);
  796.     storage.requestDataPtr = (Address) NIL;
  797.     storage.requestDataSize = 0;
  798.  
  799.     storage.replyParamPtr = (Address) attrPtr;
  800.     storage.replyParamSize = sizeof(Fs_Attributes);
  801.     storage.replyDataPtr = (Address) NIL;
  802.     storage.replyDataSize = 0;
  803.  
  804.     status = Rpc_Call(fileIDPtr->serverID, RPC_FS_GET_IO_ATTR, &storage);
  805.     /*
  806.      * We punt on I/O server recovery, and mask errors so a stat() works.
  807.      */
  808.     if (status != SUCCESS) {
  809.     printf(
  810.         "Fsrmt_GetIOAttr failed <%x>: device <%d,%d> at server %d\n",
  811.         status, fileIDPtr->major, fileIDPtr->minor, fileIDPtr->serverID);
  812.     status = SUCCESS;
  813.     }
  814.  
  815.     return(status);
  816. }
  817.  
  818. /*
  819.  *----------------------------------------------------------------------
  820.  *
  821.  * Fsrmt_RpcGetIOAttr --
  822.  *
  823.  *    Service stub for the RPC_FS_GET_IO_ATTR call.  This calls
  824.  *    the stream-type routine to get attributes cached at the I/O server.
  825.  *
  826.  * Results:
  827.  *    If this procedure returns SUCCESS then a reply has been sent to
  828.  *    the client.  If the arguments are bad then an error is 
  829.  *    returned and the main level sends back an error reply.
  830.  *
  831.  * Side effects:
  832.  *    None.
  833.  *
  834.  *----------------------------------------------------------------------
  835.  */
  836. /*ARGSUSED*/
  837. ReturnStatus
  838. Fsrmt_RpcGetIOAttr(srvToken, clientID, command, storagePtr)
  839.     ClientData          srvToken;    /* Handle on server process passed to
  840.                       * Rpc_Reply */
  841.     int          clientID;    /* Sprite ID of client host */
  842.     int          command;    /* IGNORED */
  843.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  844.                      * request buffers and also indicate 
  845.                      * the exact amount of data in the 
  846.                      * request buffers.  The reply fields 
  847.                      * are initialized to NIL for the
  848.                       * pointers and 0 for the lengths.  
  849.                      * This can be passed to Rpc_Reply */
  850. {
  851.     register ReturnStatus    status;
  852.     register Fs_HandleHeader    *hdrPtr;
  853.     register Fs_FileID        *fileIDPtr;
  854.     Fs_Attributes        *attrPtr;
  855.     Fs_GetAttrResultsParam    *getAttrResultsParamPtr;
  856.  
  857.     getAttrResultsParamPtr =
  858.         (Fs_GetAttrResultsParam *) storagePtr->requestParamPtr;
  859.     fileIDPtr = &(getAttrResultsParamPtr->attrResults.fileID);
  860.     attrPtr = &(getAttrResultsParamPtr->attrResults.attrs);
  861.  
  862.     hdrPtr = VerifyIOHandle(fileIDPtr);
  863.     if (hdrPtr != (Fs_HandleHeader *) NIL) {
  864.     /*
  865.      * If someone has the I/O device open we'll have a handle and
  866.      * should go get the access and modify times.
  867.      */
  868.     fs_Stats.srvName.getIOAttrs++;
  869.     Fsutil_HandleUnlock(hdrPtr);
  870.     status = (*fsio_StreamOpTable[hdrPtr->fileID.type].getIOAttr)
  871.         (&hdrPtr->fileID, clientID, attrPtr);
  872. #ifdef lint
  873.     status = Fsio_DeviceGetIOAttr(&hdrPtr->fileID, rpc_SpriteID, attrPtr);
  874.     status = Fsio_PipeGetIOAttr(&hdrPtr->fileID, rpc_SpriteID, attrPtr);
  875.     status = FspdevControlGetIOAttr(&hdrPtr->fileID, rpc_SpriteID,attrPtr);
  876. #endif lint
  877.     Fsutil_HandleRelease(hdrPtr, FALSE);
  878.     } else {
  879.     /*
  880.      * No information to add. We just return what was passed to us.
  881.      */
  882.     status = SUCCESS;
  883.     }
  884.     if (status == SUCCESS) {
  885.     storagePtr->replyParamPtr = (Address) attrPtr;
  886.     storagePtr->replyParamSize = sizeof(Fs_Attributes);
  887.     }
  888.     /*
  889.      * No clean-up call-back needed because we are returning the attributes
  890.      * that are sitting in the request buffer.
  891.      */
  892.     Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL, (ClientData)NIL);
  893.     return(SUCCESS);
  894. }
  895.  
  896. /*
  897.  *----------------------------------------------------------------------
  898.  *
  899.  * Fsrmt_SetIOAttr --
  900.  *
  901.  *    Set the attributes cached at a remote I/O server.  This makes the
  902.  *    RPC_FS_SET_IO_ATTR RPC to the I/O server which then calls
  903.  *    stream-type setIOAttrs routine.
  904.  *
  905.  * Results:
  906.  *    An error code.
  907.  *
  908.  * Side effects:
  909.  *    Set attributes cached with the I/O server.
  910.  *
  911.  *----------------------------------------------------------------------
  912.  */
  913. /*ARGSUSED*/
  914. ReturnStatus
  915. Fsrmt_SetIOAttr(fileIDPtr, attrPtr, flags)
  916.     register Fs_FileID        *fileIDPtr;    /* Remote device/pipe fileID */
  917.     register Fs_Attributes    *attrPtr;    /* Attributes to copy */
  918.     int                flags;        /* What attributes to set */
  919. {
  920.     register ReturnStatus    status;
  921.     Rpc_Storage            storage;
  922.     FsRemoteSetAttrParams    setAttrParam;
  923.  
  924.     setAttrParam.fileID = *fileIDPtr;
  925.     setAttrParam.attrs = *attrPtr;
  926.     setAttrParam.flags = flags;
  927.     /*
  928.      * We have to fix up the fileID of control handles in the case that
  929.      * the pseudo-device server is remote from us.  The problem is that
  930.      * we have to RPC to the pseduo-device server, but the fileID of the
  931.      * control stream (where the access/modify times are) has the
  932.      * file serverID.  Fortuneatly this is in the regular attributes so
  933.      * we can patch it up.  We add two lines of code here instead of
  934.      * nearly duplicating this procedure into a FsRmtControlSetIOAttr
  935.      * routine that has the patch.
  936.      */
  937.     if (fileIDPtr->type == FSIO_RMT_CONTROL_STREAM) {
  938.     setAttrParam.fileID.serverID = attrPtr->serverID;
  939.     }
  940.     storage.requestParamPtr = (Address) &setAttrParam;
  941.     storage.requestParamSize = sizeof(FsRemoteSetAttrParams);
  942.     storage.requestDataPtr = (Address) NIL;
  943.     storage.requestDataSize = 0;
  944.  
  945.     storage.replyParamPtr = (Address) NIL;
  946.     storage.replyParamSize = 0;
  947.     storage.replyDataPtr = (Address) NIL;
  948.     storage.replyDataSize = 0;
  949.  
  950.     status = Rpc_Call(fileIDPtr->serverID, RPC_FS_SET_IO_ATTR, &storage);
  951.     /*
  952.      * We punt on I/O server recovery, and mask errors so a chmod() works.
  953.      */
  954.     if (status != SUCCESS) {
  955.     printf(
  956.         "Fsrmt_SetIOAttr failed <%x>: device <%d,%d> at server %d\n",
  957.         status, fileIDPtr->major, fileIDPtr->minor, fileIDPtr->serverID);
  958.     status = SUCCESS;
  959.     }
  960.     return(status);
  961. }
  962.  
  963. /*
  964.  *----------------------------------------------------------------------
  965.  *
  966.  * Fsrmt_RpcSetIOAttr --
  967.  *
  968.  *    Service stub for the RPC_FS_SET_IO_ATTR call.  This calls
  969.  *    the stream-type routine to set attributes cached at the I/O server.
  970.  *
  971.  * Results:
  972.  *    If this procedure returns SUCCESS then a reply has been sent to
  973.  *    the client.  If the arguments are bad then an error is 
  974.  *    returned and the main level sends back an error reply.
  975.  *
  976.  * Side effects:
  977.  *    None.
  978.  *
  979.  *----------------------------------------------------------------------
  980.  */
  981. /*ARGSUSED*/
  982. ReturnStatus
  983. Fsrmt_RpcSetIOAttr(srvToken, clientID, command, storagePtr)
  984.     ClientData          srvToken;    /* Handle on server process passed to
  985.                       * Rpc_Reply */
  986.     int          clientID;    /* Sprite ID of client host */
  987.     int          command;    /* IGNORED */
  988.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  989.                      * request buffers and also indicate 
  990.                      * the exact amount of data in the 
  991.                      * request buffers.  The reply fields 
  992.                      * are initialized to NIL for the
  993.                       * pointers and 0 for the lengths.  
  994.                      * This can be passed to Rpc_Reply */
  995. {
  996.     register ReturnStatus    status;
  997.     register Fs_HandleHeader    *hdrPtr;
  998.     register Fs_FileID        *fileIDPtr;
  999.     Fs_Attributes        *attrPtr;
  1000.     FsRemoteSetAttrParams    *setAttrParamPtr;
  1001.  
  1002.     setAttrParamPtr =
  1003.         (FsRemoteSetAttrParams *) storagePtr->requestParamPtr;
  1004.     fileIDPtr = &(setAttrParamPtr->fileID);
  1005.     attrPtr = &(setAttrParamPtr->attrs);
  1006.  
  1007.    fs_Stats.srvName.setIOAttrs++;
  1008.    hdrPtr = VerifyIOHandle(fileIDPtr);
  1009.     if (hdrPtr == (Fs_HandleHeader *) NIL) {
  1010.     /*
  1011.      * Noone has the I/O device open so we don't have a handle.
  1012.      * Return SUCCESS but take no action.
  1013.      */
  1014.     return(SUCCESS);
  1015.     } 
  1016.     Fsutil_HandleUnlock(hdrPtr);
  1017.  
  1018.     status = (*fsio_StreamOpTable[hdrPtr->fileID.type].setIOAttr)
  1019.         (&hdrPtr->fileID, attrPtr, setAttrParamPtr->flags);
  1020. #ifdef lint
  1021.     status = Fsio_DeviceSetIOAttr(&hdrPtr->fileID, attrPtr,setAttrParamPtr->flags);
  1022.     status = Fsio_PipeSetIOAttr(&hdrPtr->fileID, attrPtr, setAttrParamPtr->flags);
  1023.     status = FspdevControlSetIOAttr(&hdrPtr->fileID, attrPtr,
  1024.                     setAttrParamPtr->flags);
  1025. #endif lint
  1026.  
  1027.     Fsutil_HandleRelease(hdrPtr, FALSE);
  1028.  
  1029.     /*
  1030.      * No clean-up call-back needed because there are no reply parameters.
  1031.      */
  1032.     Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL, (ClientData)NIL);
  1033.     return(SUCCESS);
  1034. }
  1035.  
  1036. /*
  1037.  *----------------------------------------------------------------------
  1038.  *
  1039.  * VerifyIOHandle --
  1040.  *
  1041.  *    Verify an I/O handle from a remote client.  This is only used when
  1042.  *    getting/setting attributes.  We do not require that the client be
  1043.  *    listed for the I/O handle because in two important cases it won't be.
  1044.  *    The first is if we are the I/O server for a device, and someone
  1045.  *    does a Fs_GetAttributes(pathname, ...).  We are contacted for the
  1046.  *    latest I/O attributes, and the client won't have opened the device.
  1047.  *    The second case is if we are the name server and someone is doing
  1048.  *    a Fs_GetAttributesID(streamID, ...).  Here the I/O server has the
  1049.  *    client in its list, but we (the name server) do not.
  1050.  *
  1051.  * Results:
  1052.  *    A locked pointer to the I/O handle if it exists.
  1053.  *
  1054.  * Side effects:
  1055.  *    The returned handle must be released because we fetch it here.
  1056.  *
  1057.  *----------------------------------------------------------------------
  1058.  */
  1059. static Fs_HandleHeader *
  1060. VerifyIOHandle(fileIDPtr)
  1061.     Fs_FileID *fileIDPtr;
  1062. {
  1063.     if (fileIDPtr->type <= 0 || fileIDPtr->type >= FSIO_NUM_STREAM_TYPES) {
  1064.     printf(
  1065.         "Bad stream type (%d) in VerifyIOHandle.\n",
  1066.         fileIDPtr->type);
  1067.     return((Fs_HandleHeader *)NIL);
  1068.     } else {
  1069.     fileIDPtr->type = fsio_RmtToLclType[fileIDPtr->type];
  1070.     }
  1071.     return(Fsutil_HandleFetch(fileIDPtr));
  1072. }
  1073.